﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Ioc;

using HandyControl.Controls;
using HandyControl.Data;
using HandyControl.Tools.Extension;

using Microsoft.Win32;

using Stock.Controls;
using Stock.Core;
using Stock.Model;
using Stock.Service;
using Stock.Util;

using MessageBox = HandyControl.Controls.MessageBox;

namespace Stock.ViewModel
{
    public class MainViewModel : ViewModelBase
    {
        private AppService appService;
        private AppConfigService appConfigService;
        private AppConfigModel configModel;
        private EasyMoneyService easyMoneyService;
        private Timer dataTimer;
        private Timer timer;
        private Timer infoTimer;
        private Timer versionTimer;
        private int index = 0;
        private MySprite infoSprite;

        public MainViewModel()
        {
            Init();
            InitTimer();
        }

        #region 属性和事件
        private System.Windows.Window _window;

        public System.Windows.Window Window { get => _window; set => _window = value; }

        private double _todayTotalPrice;
        private double _totalPrice;
        private string _todayTotalPricePercent;
        private string _totalPricePercent;
        private bool _eyeOpend;
        private bool _checkUpdateFlag = false;

        private string s1, s2, s3;

        public bool EyeOpend { get => _eyeOpend; set => Set(ref _eyeOpend, value); }

        /// <summary>
        /// 今日收益
        /// </summary>
        public string TodayTotalPriceString { get => s1; set => Set(ref s1, value); }

        public double TodayTotalPrice { get => _todayTotalPrice; set => Set(ref _todayTotalPrice, value); }

        /// <summary>
        /// 今日收益百分比
        /// </summary>
        public string TodayTotalPricePercent { get => _todayTotalPricePercent; set => Set(ref _todayTotalPricePercent, value); }

        /// <summary>
        /// 持有收益
        /// </summary>
        public string TotalPriceString { get => s2; set => Set(ref s2, value); }

        public double TotalPrice { get => _totalPrice; set => Set(ref _totalPrice, value); }

        /// <summary>
        /// 持有收益百分比
        /// </summary>

        public string TotalPricePercent { get => _totalPricePercent; set => Set(ref _totalPricePercent, value); }

        private double _totalMarketValue;

        /// <summary>
        /// 总市值
        /// </summary>
        public string TotalMarketValueString { get => s3; set => Set(ref s3, value); }

        public double TotalMarketValue { get => _totalMarketValue; set => Set(ref _totalMarketValue, value); }

        private string _currentTime;

        /// <summary>
        /// 当前时间
        /// </summary>
        public string CurrentTime { get => _currentTime; set => Set(ref _currentTime, value); }

        private bool _showInfo;

        /// <summary>
        /// 是否显示信息框
        /// </summary>
        public bool ShowInfo
        {
            get => _showInfo;
            set
            {
                Set(ref _showInfo, value);
                SetWindowVisibility(value);
            }
        }

        /// <summary>
        /// 信息框提示文本
        /// </summary>
        private string _notifyText;

        public string NotifyText { get => _notifyText; set => Set(ref _notifyText, value); }

        private bool _notifyVisible;

        public bool NotifyVisible { get => _notifyVisible; set => Set(ref _notifyVisible, value); }

        private bool _versionVisible;

        public bool VersionVisible { get => _versionVisible; set => Set(ref _versionVisible, value); }

        private bool _showTopMenuItem;
        private bool _showBottomMenuItem;
        private bool _showSeparatorMenuItem;
        private bool _showDetailMenuItem;

        public bool ShowTopMenuItem { get => _showTopMenuItem; set => Set(ref _showTopMenuItem, value); }

        public bool ShowBottomMenuItem { get => _showBottomMenuItem; set => Set(ref _showBottomMenuItem, value); }

        public bool ShowSeparatorMenuItem { get => _showSeparatorMenuItem; set => Set(ref _showSeparatorMenuItem, value); }

        public bool ShowDetailMenuItem { get => _showDetailMenuItem; set => Set(ref _showDetailMenuItem, value); }

        /// <summary>
        /// 程序集版本
        /// </summary>
        private string _appVersion;
        public string AppVersion { get => _appVersion; set => Set(ref _appVersion, value); }

        public RelayCommand<DataGridCellEditEndingEventArgs> CellEditEndingCmd => new RelayCommand<DataGridCellEditEndingEventArgs>(CellEditEnding);

        public RelayCommand AddCmd => new RelayCommand(Add);

        public RelayCommand HiddenCmd => new RelayCommand(Hidden);

        public RelayCommand ExitCmd => new RelayCommand(Exit);

        public RelayCommand DeleteAllCmd => new RelayCommand(DeleteAll);

        public RelayCommand ConfigCmd => new RelayCommand(Config);

        public RelayCommand UpdateAllCmd => new RelayCommand(UpdateAll);

        public RelayCommand<ContextMenuEventArgs> MenuOpeningCmd => new RelayCommand<ContextMenuEventArgs>(MenuOpening);

        public RelayCommand<int> MenuTopCmd => new RelayCommand<int>(MenuTop);
        public RelayCommand<int> MenuUpCmd => new RelayCommand<int>(MenuUp);
        public RelayCommand<int> MenuDownCmd => new RelayCommand<int>(MenuDown);
        public RelayCommand<int> MenuBottomCmd => new RelayCommand<int>(MenuBottom);
        public RelayCommand<StockViewModel> MenuTrendCmd => new RelayCommand<StockViewModel>(MenuTrend);
        public RelayCommand<StockViewModel> MenuDetailCmd => new RelayCommand<StockViewModel>(MenuDetail);
        public RelayCommand<StockViewModel> MenuDeleteCmd => new RelayCommand<StockViewModel>(MenuDelete);

        public RelayCommand<MouseButtonEventArgs> DoubleClickCmd => new RelayCommand<MouseButtonEventArgs>(DoubleClick);

        public RelayCommand SetBgCmd => new RelayCommand(SetBg);

        public RelayCommand CheckUpdateCmd => new RelayCommand(CheckUpdate);

        public RelayCommand<Button> EyeCmd => new RelayCommand<Button>(EyeOpen);

        private ObservableCollection<StockViewModel> _indexStockList;
        public ObservableCollection<StockViewModel> IndexStockList
        {
            get => _indexStockList;
            set => Set(ref _indexStockList, value);
        }

        private ObservableCollection<StockViewModel> _dataList;
        public ObservableCollection<StockViewModel> DataList
        {
            get => _dataList;
            set => Set(ref _dataList, value);
        }

        #endregion

        private async void Init()
        {
            _eyeOpend = true;
            _notifyVisible = true;

            _appVersion = StringUtil.GetVersionString(GetType());
            configModel = SimpleIoc.Default.GetInstance<AppConfigModel>();
            easyMoneyService = SimpleIoc.Default.GetInstance<EasyMoneyService>();
            appService = SimpleIoc.Default.GetInstance<AppService>();
            appConfigService = SimpleIoc.Default.GetInstance<AppConfigService>();

            IndexStockList = new ObservableCollection<StockViewModel>(AppUtil.ToViewModelList(await easyMoneyService.GetStockList(StockType.IndexStock), true));
            DataList = new ObservableCollection<StockViewModel>(AppUtil.ToViewModelList(await easyMoneyService.GetStockList(StockType.Stock), _eyeOpend));
            await Update();
            await CheckVersion(false);
        }

        private void InitTimer()
        {
            timer = new Timer(configModel.CurrentTimeInterval * 1000);
            timer.Elapsed += Timer_Elapsed;
            timer.Start();

            versionTimer = new Timer(AppConst.VALUE_VERSION_INTERVAL);
            versionTimer.Elapsed += VersionTimer_ElapsedAsync;
            versionTimer.Start();
        }

        #region Timer 事件
        private void InfoTimer_Elapsed(object sender, ElapsedEventArgs e)
        {
            if (StringUtil.IsEmpty(_dataList))
            {
                return;
            }

            IEnumerable<StockViewModel> list = _dataList.Where(m => m.Number > 0);
            int count = list.Count();
            if (count <= 0)
            {
                return;
            }

            if (index >= count)
            {
                index = 0;
            }

            var model = list.ElementAt(index);
            NotifyText = GetNotifyText(model);

            index++;

            if (!_showInfo)
            {
                return;
            }

            var infoType = (StockInfoType)configModel.InfoType;
            if (infoType == StockInfoType.Growl)
            {
                string changeFlag = model.Change > 0 ? "↑" : "↓";
                SendNotification($"{model.Name} [{changeFlag}] [{model.Change}] [{model.TodayPrice}] [{_todayTotalPrice}]", model.Change > 0);
            }
            else if (infoType == StockInfoType.Sprite)
            {
                SendSprite(model);
            }
        }

        private void Timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            CurrentTime = $"{DateTime.Now:yyyy/MM/dd HH:mm:ss}({StringUtil.GetDayOfWeekString()})";

            bool workTime = IsWorkTime();
            if (workTime)
            {
                if (dataTimer == null)
                {
                    dataTimer = new Timer(configModel.StockShowTimeInterval * 1000);
                    dataTimer.Elapsed += DataTimer_ElapsedAsync;
                    dataTimer.Start();
                }
                else
                {
                    if (!dataTimer.Enabled)
                    {
                        dataTimer.Start();
                    }
                }
            }
            else
            {
                if (dataTimer != null)
                {
                    dataTimer.Stop();
                }
            }

            if (configModel.NotWorkTimeShowInfo || workTime)
            {
                if (infoTimer == null)
                {
                    infoTimer = new Timer(configModel.InfoShowTimeInterval * 1000);
                    infoTimer.Elapsed += InfoTimer_Elapsed;
                    infoTimer.Start();
                }
                else
                {
                    if (!infoTimer.Enabled)
                    {
                        infoTimer.Start();
                    }
                }
            }
        }

        private async void DataTimer_ElapsedAsync(object sender, ElapsedEventArgs e)
        {
            await Update();
        }

        private void VersionTimer_ElapsedAsync(object sender, ElapsedEventArgs e)
        {
            if (_versionVisible)
            {
                return;
            }

            Application.Current.Dispatcher?.Invoke(async () =>
            {
                await CheckVersion(false);
            });
        }

        private bool IsWorkTime()
        {
            var dayOfWeek = DateTime.Now.DayOfWeek;
            if (dayOfWeek == DayOfWeek.Saturday || dayOfWeek == DayOfWeek.Sunday)
            {
                return false;
            }

            int hour = DateTime.Now.Hour;
            int minute = DateTime.Now.Minute;
            if (hour > 11)
            {
                return hour >= 13 && hour < 15;
            }
            else
            {
                if (hour == 10 || (hour == 9 && minute >= 15) || (hour == 11 && minute <= 30))
                {
                    return true;
                }
                return false;
            }
        }
        #endregion

        #region 股票操作
        private void EyeOpen(Button btn)
        {
            EyeOpend = _eyeOpend ? false : true;

            string imgKey = _eyeOpend ? AppConst.RES_KEY_EYE_OPEN : AppConst.RES_KEY_EYE_CLOSE;
            var img = Application.Current.GetResource(imgKey);
            if (img != null)
            {
                btn.Content = img;
            }

            UpdateEyePrice();
        }

        private async void Add()
        {
            var vm = SimpleIoc.Default.GetInstance<AddStockViewModel>();
            vm.Clear();

            var content = new AddStockContent()
            {
                DataContext = vm
            };

            var model = await Dialog.Show(content).GetResultAsync<StockViewModel>();
            if (model != null && model.Valid())
            {
                var existModel = _dataList.FirstOrDefault(m => m.Code == model.Code);
                if (existModel == null)
                {
                    AddStock(model);
                    await UpdateToFile(model);
                    await Update();
                }
            }
        }

        private void AddStock(StockViewModel model)
        {
            int minNo = 0;
            if (StringUtil.IsNotEmpty(_dataList))
            {
                minNo = _dataList.Min(m => m.No);
            }
            else
            {
                minNo = AppConst.VALUE_STOCK_LIST_MAX_COUNT;
            }
            model.No = minNo - 1;
            _dataList.Add(model);
        }

        private async void CellEditEnding(DataGridCellEditEndingEventArgs e)
        {
            if (e.EditAction == DataGridEditAction.Commit)
            {
                var box = e.EditingElement as System.Windows.Controls.TextBox;
                string text = box.Text;
                if (string.IsNullOrEmpty(text))
                {
                    return;
                }
                double value = StringUtil.ToDouble(text);
                if (value < 0)
                {
                    return;
                }

                var model = e.Row.DataContext as StockViewModel;
                var index = e.Column.DisplayIndex;
                if (index == 5)
                {
                    model.CostPrice = StringUtil.ToFixed(value, 4);
                    await UpdateToFile(model);
                }
                else if (index == 6)
                {
                    model.Number = StringUtil.ToFixed(value);
                    await UpdateToFile(model);
                }
            }
        }

        private async void MenuDelete(StockViewModel model)
        {
            if (MessageBox.Ask(AppConst.TEXT_DELETE_ASK, AppConst.TEXT_APP_NAME) == MessageBoxResult.OK)
            {
                if (StringUtil.IsNotEmpty(_dataList))
                {
                    if (model != null)
                    {
                        _dataList.Remove(model);
                        await UpdateToFile();
                    }
                }
            }
        }

        public async void DeleteAll()
        {
            if (MessageBox.Ask(AppConst.TEXT_DELETE_ALL_ASK, AppConst.TEXT_APP_NAME) == MessageBoxResult.OK)
            {
                if (StringUtil.IsNotEmpty(_dataList))
                {
                    _dataList.Clear();
                    await UpdateToFile();
                }
            }
        }

        public async void UpdateAll()
        {
            if (StringUtil.IsNotEmpty(_dataList))
            {
                foreach (var item in _dataList)
                {
                    var model = item.ToModel();
                    easyMoneyService.UpdateMarketType(model);
                    item.UpdateMarketType(model);
                }
                await UpdateToFile();
                MessageBox.Success(AppConst.TEXT_UPDATE_ALL_SUCCESS, AppConst.TEXT_APP_NAME);
            }
        }

        private async Task UpdateToFile(StockViewModel model)
        {
            model.UpdatePrice(_eyeOpend);
            await UpdateToFile();
        }

        private async Task UpdateToFile(bool updatePrice = true)
        {
            await easyMoneyService.Update(StockType.Stock, AppUtil.ToModelList(_dataList));
            if (updatePrice)
            {
                UpdateTotalPrice();
            }
        }

        private async Task Update()
        {
            if (_indexStockList != null && _indexStockList.Count > 0)
            {
                foreach (StockViewModel item in _indexStockList)
                {
                    var model = await easyMoneyService.GetStockModel(item.ToModel(), true);
                    item.Update(model, true);
                }
            }

            if (StringUtil.IsNotEmpty(_dataList))
            {
                for (int i = 0; i < _dataList.Count; i++)
                {
                    var item = _dataList[i];
                    var model = await easyMoneyService.GetStockModel(item.ToModel(), false);
                    item.Update(model, _eyeOpend);
                }

                UpdateTotalPrice();
            }
        }

        private void UpdateEyePrice()
        {
            if (StringUtil.IsNotEmpty(_dataList))
            {
                foreach (var item in _dataList)
                {
                    item.UpdatePrice(_eyeOpend);
                }
                UpdateTotalPrice();
            }
        }

        private void UpdateTotalPrice()
        {
            TodayTotalPrice = StringUtil.ToFixed(_dataList.Sum(m => m.TodayPrice));
            TotalPrice = StringUtil.ToFixed(_dataList.Sum(m => m.TotalPrice));
            TotalMarketValue = StringUtil.ToFixed(_dataList.Where(m => m.Number > 0).Sum(m => m.Number * m.Price));

            double todayTotalPricePercent = 0;
            double totalPricePercent = 0;
            if (_totalMarketValue > 0)
            {
                todayTotalPricePercent = StringUtil.ToFixed(_todayTotalPrice * 100 / _totalMarketValue);
                totalPricePercent = StringUtil.ToFixed(_totalPrice * 100 / _totalMarketValue);
            }

            TodayTotalPriceString = StringUtil.ToEyeString(_todayTotalPrice, _eyeOpend, true);
            TotalPriceString = StringUtil.ToEyeString(_totalPrice, _eyeOpend, true);
            TotalMarketValueString = StringUtil.ToEyeString(_totalMarketValue, _eyeOpend, true);
            TodayTotalPricePercent = $"{StringUtil.ToEyeString(todayTotalPricePercent, _eyeOpend)}%";
            TotalPricePercent = $"{StringUtil.ToEyeString(totalPricePercent, _eyeOpend)}%";

            StockWarning(todayTotalPricePercent);
        }

        private void StockWarning(double todayTotalPricePercent)
        {
            if (configModel.IsOpenHappySwich())
            {
                if (todayTotalPricePercent >= configModel.StockHappyPercent)
                {
                    SendWarningInfo(true);
                }
            }

            if (configModel.IsOpenSadSwich())
            {
                if (todayTotalPricePercent <= configModel.StockSadPercent)
                {
                    SendWarningInfo(false);
                }
            }
        }

        private void DoubleClick(MouseButtonEventArgs e)
        {
            if (e.Source is Card card)
            {
                if (card.DataContext is StockViewModel model)
                {
                    ShowStockTrend(model, StockType.IndexStock);
                }
            }
            else if (e.Source is DataGrid grid)
            {
                Point aP = e.GetPosition(grid);
                IInputElement obj = grid.InputHitTest(aP);
                DependencyObject target = obj as DependencyObject;

                while (target != null)
                {
                    if (target is DataGridCell cell)
                    {
                        string name = cell.Column.SortMemberPath;
                        if (name == AppConst.NAME_STOCK_COST_PRICE || name == AppConst.NAME_STOCK_NUMBER)
                        {
                            break;
                        }
                    }
                    if (target is DataGridRow dr)
                    {
                        if (dr.Item is StockViewModel model)
                        {
                            ShowStockTrend(model, StockType.Stock);
                        }
                        break;
                    }
                    target = VisualTreeHelper.GetParent(target);
                }
            }
        }

        private void ShowStockTrend(StockViewModel model, StockType type)
        {
            if (model == null) return;

            if (model.IsOTCFund())
            {
                var info = new GrowlInfo() { WaitTime = 5, IsCustom = true, Message = AppConst.TEXT_NOT_SUPPORT_DETAIL_STOCK };
                Growl.Warning(info);
                return;
            }

            string url = type == StockType.IndexStock ? string.Format(AppConst.EASY_MONEY_DETAIL1_URL, model.MktNum, model.Code) : string.Format(AppConst.EASY_MONEY_DETAIL2_URL, model.Code, model.MarketType);
            StockTrendViewModel vm = SimpleIoc.Default.GetInstance<StockTrendViewModel>();
            vm.Url = url;
            StockTrendWindow window = new StockTrendWindow()
            {
                DataContext = vm
            };
            try
            {
                _ = window.ShowDialog();
            }
            catch { }
        }

        private void ShowStockDetail(StockViewModel model)
        {
            if (model == null || !model.IsFund()) return;

            StockDetailViewModel vm = SimpleIoc.Default.GetInstance<StockDetailViewModel>();
            vm.Code = model.Code;
            vm.PageIndex = 1;
            StockDetailWindow window = new StockDetailWindow() { DataContext = vm };
            try
            {
                _ = window.ShowDialog();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        private void MenuOpening(ContextMenuEventArgs e)
        {
            if (e.OriginalSource is Border border)
            {
                if (border.DataContext is StockViewModel model)
                {
                    e.Handled = false;

                    int index = GetStockIndex(StockType.Stock, model);
                    if (index == -1) return;

                    if (index == 0)
                    {
                        ShowTopMenuItem = false;
                    }
                    else
                    {
                        ShowTopMenuItem = true;
                    }

                    if (index == _dataList.Count - 1)
                    {
                        ShowBottomMenuItem = false;
                    }
                    else
                    {
                        ShowBottomMenuItem = true;
                    }

                    if (model.IsFund())
                    {
                        ShowDetailMenuItem = true;
                    }
                    else
                    {
                        ShowDetailMenuItem = false;
                    }

                    ShowSeparatorMenuItem = _showTopMenuItem || _showBottomMenuItem;
                    return;
                }
            }
            e.Handled = true;
        }

        public void MenuTrend(StockViewModel model)
        {
            ShowStockTrend(model, StockType.Stock);
        }

        public void MenuDetail(StockViewModel model)
        {
            ShowStockDetail(model);
        }

        private async void MenuTop(int index)
        {
            int firstIndex = 0;
            if (index <= firstIndex) return;

            _dataList[index].No = _dataList[firstIndex].No + 1;

            MoveListItem(StockType.Stock, index, firstIndex);
            await UpdateToFile(false);
        }

        private void MenuUp(int index)
        {
            if (index <= 0) return;

            ExchangeItem(index, index - 1);
        }

        private void MenuDown(int index)
        {
            int nextIndex = index + 1;
            if (nextIndex > _dataList.Count - 1) return;

            ExchangeItem(index, nextIndex);
        }

        private async void MenuBottom(int index)
        {
            int maxIndex = _dataList.Count - 1;
            if (index >= maxIndex) return;

            _dataList[index].No = _dataList[maxIndex].No - 1;

            MoveListItem(StockType.Stock, index, maxIndex);
            await UpdateToFile(false);
        }

        private async void ExchangeItem(int index, int changeIndex)
        {
            var item = _dataList[index];
            int oldNo = item.No;
            item.No = _dataList[changeIndex].No;
            _dataList[changeIndex].No = oldNo;

            MoveListItem(StockType.Stock, index, changeIndex);
            await UpdateToFile(false);
        }

        private void MoveListItem(StockType type, int oldIndex, int newIndex)
        {
            if (type == StockType.IndexStock)
            {
                _indexStockList.Move(oldIndex, newIndex);
            }
            else
            {
                _dataList.Move(oldIndex, newIndex);
            }
        }

        private int GetStockIndex(StockType type, StockViewModel model)
        {
            int index;
            if (type == StockType.IndexStock)
            {
                index = _indexStockList.IndexOf(model);
            }
            else
            {
                index = _dataList.IndexOf(model);
            }
            return index;
        }
        #endregion

        #region App操作
        private async void Config()
        {
            var vm = SimpleIoc.Default.GetInstance<AppConfigViewModel>();
            vm.Result = configModel.Copy();
            vm.SpriteBgColor = configModel.SpriteBgColor;
            vm.ZhangColor = configModel.ZhangColor;
            vm.DieColor = configModel.DieColor;

            var content = new AppConfigContent()
            {
                DataContext = vm
            };

            var model = await Dialog.Show(content).GetResultAsync<AppConfigModel>();
            if (model != null)
            {
                if (configModel.AutoStart != model.AutoStart)
                {
                    AppUtil.SetMeStart(model.AutoStart == 1);
                }
                if (configModel.SkinType != model.SkinType)
                {
                    Application.Current.SetSkin(model.SkinType);
                }
                if (configModel.StockShowTimeInterval != model.StockShowTimeInterval)
                {
                    if (dataTimer != null)
                    {
                        dataTimer.Interval = model.StockShowTimeInterval * 1000;
                    }
                }
                if (configModel.InfoShowTimeInterval != model.InfoShowTimeInterval)
                {
                    if (infoTimer != null)
                    {
                        infoTimer.Interval = model.InfoShowTimeInterval * 1000;
                    }
                }
                if (configModel.CurrentTimeInterval != model.CurrentTimeInterval)
                {
                    if (timer != null)
                    {
                        timer.Interval = model.CurrentTimeInterval * 1000;
                    }
                }
                configModel.Update(model);
                appConfigService.Update(configModel);
            }
        }

        private async Task CheckVersion(bool noUpdateTipFlag)
        {
            string updaterPath = GetUpdaterAppPath();
            if (!FileUtil.ExistFile(updaterPath))
            {
                var info = new GrowlInfo() { StaysOpen = true, Message = AppConst.TEXT_NOT_SUPPORT_UPDATE };
                Growl.Warning(info);
                return;
            }

            var updateModel = await appService.GetLastVersion();
            if (updateModel.HasVersion())
            {
                Version currentVersion = StringUtil.GetVersion(GetType());
                if (updateModel.Version > currentVersion)
                {
                    if (_showInfo)
                    {
                        ShowInfo = false;
                    }
                    string askMsg = string.Format(AppConst.TEXT_UPDATE_IS_NOW, updateModel.Version.ToString(), updateModel.Content);
                    if (MessageBox.Ask(askMsg, AppConst.TEXT_APP_NAME) == MessageBoxResult.OK)
                    {
                        VersionVisible = false;
                        UpdateApp();
                    }
                    else
                    {
                        VersionVisible = true;
                    }
                }
                else
                {
                    if (noUpdateTipFlag)
                    {
                        var info = new GrowlInfo() { WaitTime = 5, Message = string.Format(AppConst.TEXT_CURRENT_VERSION_IS_NEW, currentVersion.ToString(), updateModel.Content) };
                        Growl.Info(info);
                    }
                }
            }
            _checkUpdateFlag = false;
        }

        private async void CheckUpdate()
        {
            if (_checkUpdateFlag)
            {
                return;
            }

            _checkUpdateFlag = true;
            await CheckVersion(true);
        }

        private void UpdateApp()
        {
            ProcessUtil.Start(GetUpdaterAppPath());
        }

        private void SetBg()
        {
            RegistryKey controlPanelKey = Registry.CurrentUser.OpenSubKey(@"Control Panel", true);
            if (controlPanelKey != null)
            {
                RegistryKey desktopKey = controlPanelKey.OpenSubKey("Desktop", true);
                if (desktopKey != null)
                {
                    desktopKey.SetValue("TileWallpaper", "0");//0 居中 1  平铺 默认
                    desktopKey.SetValue("WallpaperStyle", "0");//2 拉伸
                    desktopKey.Close();
                }
                controlPanelKey.Close();
            }

            string fileName = FileUtil.GetFilePath(@"Img\desktop_bg.bmp");
            AppUtil.CreateBitmapFromVisual(_window, fileName);
            Win32Util.SystemParametersInfo(20, 1, fileName, 1);
        }

        private string GetUpdaterAppPath()
        {
            return FileUtil.GetFilePath(string.Format(@"{0}\{0}.exe", AppConst.TEXT_APP_UPDATER_EN_NAME));
        }

        private void Hidden()
        {
            ShowInfo = false;
            HiddenWindow();
        }

        private void Exit()
        {
            NotifyVisible = false;
            timer?.Stop();
            dataTimer?.Stop();
            infoTimer?.Stop();
            versionTimer?.Stop();
            Application.Current.Shutdown();
        }

        private void ShowWindow()
        {
            _window.Show();
        }

        private void HiddenWindow()
        {
            _window.Hide();
        }
        #endregion

        #region 发送消息
        private void SendWarningInfo(bool isHappy)
        {
            string text = isHappy ? AppConst.TEXT_HAPPY : AppConst.TEXT_SAD;
            GrowlInfo info = new GrowlInfo()
            {
                Message = text,
                ShowCloseButton = true,
                ShowDateTime = false,
                StaysOpen = false,
                Type = InfoType.Info,
                IsCustom = true,
                IconBrushKey = ResourceToken.DarkAccentBrush,
                WaitTime = configModel.InfoWaitTimeInterval
            };
            if (_showInfo)
            {
                info.BeforeShow = GrowlBeforShow;
                info.Token = AppConst.TOKEN_NOTIFY_ICON;
            }
            Application.Current.Dispatcher?.Invoke(() =>
            {
                if (_showInfo)
                {
                    Growl.SuccessGlobal(info);
                }
                else
                {
                    Growl.Info(info);
                }
            });
        }
        private void SetWindowVisibility(bool flag)
        {
            var infoType = (StockInfoType)configModel.InfoType;
            if (infoType == StockInfoType.Sprite && infoSprite != null)
            {
                infoSprite.Visibility = flag ? Visibility.Visible : Visibility.Hidden;
            }
            if (flag)
            {
                HiddenWindow();
            }
            else
            {
                ShowWindow();
            }
        }

        private void SendSprite(StockViewModel model)
        {
            Application.Current.Dispatcher?.Invoke(() =>
            {
                var vm = SimpleIoc.Default.GetInstance<StockSpriteViewModel>();
                vm.Stock = model;
                vm.NotifyText = _notifyText;
                vm.TodayTotalPrice = _todayTotalPrice;
                vm.TotalPrice = _totalPrice;
                vm.TodayTotalPriceString = s1;
                vm.TotalPriceString = s2;

                if (vm.DoubleClick == null)
                {
                    vm.DoubleClick = ShowWindow;
                }
                if (vm.Hidden == null)
                {
                    vm.Hidden = Hidden;
                }
                if (vm.Exit == null)
                {
                    vm.Exit = Exit;
                }

                if (infoSprite == null)
                {
                    var content = new StockSpriteContent() { DataContext = vm };
                    infoSprite = new MySprite();
                    infoSprite.Show(content);
                }
                else
                {
                    infoSprite.Update(vm);
                    if (infoSprite.Visibility == Visibility.Hidden)
                    {
                        infoSprite.Visibility = Visibility.Visible;
                    }
                }
            });
        }
        private void SendNotification(string text, bool flag)
        {
            Application.Current.Dispatcher?.Invoke(() =>
            {
                Growl.SuccessGlobal(new GrowlInfo()
                {
                    Message = text,
                    ShowCloseButton = true,
                    ShowDateTime = false,
                    StaysOpen = false,
                    Type = InfoType.Info,
                    WaitTime = configModel.InfoWaitTimeInterval,
                    IsCustom = true,
                    FlowDirection = FlowDirection.LeftToRight,
                    IconBrushKey = flag ? ResourceToken.DarkAccentBrush : ResourceToken.DarkSuccessBrush,
                    Token = AppConst.TOKEN_NOTIFY_ICON,
                    BeforeShow = GrowlBeforShow
                });
            });
        }

        private void GrowlBeforShow(GrowlWindow window, Panel panel, Growl growl)
        {
            var position = (GrowlInfoPosition)configModel.InfoPosition;
            var area = SystemParameters.WorkArea;
            double top = 0;
            double left = 0;

            double width = panel.ActualWidth.IsNaN() ? 0 : panel.ActualWidth;
            double height = panel.ActualHeight.IsNaN() ? 0 : panel.ActualHeight;
            width = width <= 0 ? 340 : width;
            height = height <= 0 ? 70 : height;//默认值 可以显示一条信息的内容
            switch (position)
            {
                case GrowlInfoPosition.RightTop:
                    left = area.Right - width;
                    break;
                case GrowlInfoPosition.RightButtom:
                    top = area.Bottom - height;
                    left = area.Right - width;
                    break;
                case GrowlInfoPosition.RightMiddle:
                    top = (area.Bottom - height) / 2;
                    left = area.Right - width;
                    break;
                case GrowlInfoPosition.LeftTop:
                    break;
                case GrowlInfoPosition.LeftMiddle:
                    top = (area.Bottom - height) / 2;
                    break;
                case GrowlInfoPosition.LeftButtom:
                    top = area.Bottom - height;
                    break;
                case GrowlInfoPosition.Center:
                    top = (area.Bottom - height) / 2;
                    left = (area.Right - width) / 2;
                    break;
            }
            window.Top = top;
            window.Left = left;
        }

        private string GetNotifyText(StockViewModel model)
        {
            string split = ":  ";
            StringBuilder sb = new StringBuilder();
            sb.Append(AppConst.TEXT_STOCK_NAME).Append(split).Append(model.Name).AppendLine();
            sb.Append(AppConst.TEXT_STOCK_PRICE).Append(split).Append(model.Price).AppendLine();
            sb.Append("   ").Append(AppConst.TEXT_STOCK_CHANGE).Append(split).Append(model.Change).AppendLine();
            sb.Append("      ").Append(AppConst.TEXT_STOCK_CHANGE_PERCENT).Append(split).Append(model.ChangePercent).AppendLine();
            sb.Append(AppConst.TEXT_TODAY_PRICE).Append(split).Append(_todayTotalPrice).AppendLine();
            sb.Append(AppConst.TEXT_TOTAL_PRICE).Append(split).Append(_totalPrice).AppendLine();
            sb.Append(AppConst.TEXT_STOCK_UPDATE_TIME).Append(split).Append(model.UpdateTime);
            return sb.ToString();
        }
        #endregion
    }
}
